/*
 * twain.c -- Gadget Twain, for USB development
 * NOTE: in or out all view from host!
 */

#define DEBUG 1
#define VERBOSE

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/utsname.h>
#include <linux/device.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/suspend.h>

#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>

#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>

#include "gadget_chips.h"
#include "twain.h"



/* Globla data for this driver */
static struct twain_dev *twdev;
#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)

#define DRIVER_VERSION		"2011-01-10"
#define 	EP0_BUFSIZ		256
#define     NUM_BUF_DEF		3
#define		SIZ_BUF_DEF		(1024*1024)
#define     REQUEST_OK		0


static const char shortname [] = "twain";
static const char longname [] = "Gadget Twain";

static const char twain_protocol_name [] = "Twain Protocol";

/*
 * driver assumes self-powered hardware, and
 * has no way for users to trigger remote wakeup.
 *
 * this version autoconfigures as much as possible,
 * which is reasonable for most "bulk-only" drivers.
 */
static const char *EP_INCMD_NAME;		/* Ack back to host */
static const char *EP_OUTCMD_NAME;		/* Get cmd from host */
static const char *EP_INBULK_NAME;		/* Send raw/rgb frame to host */
static const char *EP_PREVIEW;		/* Use for preview */


static struct usb_gadget_driver twain_driver;
static int twain_major = 199;
static unsigned int outbuflen = 16384;	/* 16k */
module_param (outbuflen, uint, S_IRUGO|S_IWUSR);

enum buf_state {
	BUF_STATE_IDLE,
	BUF_STATE_EMPTY,
	BUF_STATE_FULL,
	BUF_STATE_BUSY,
};

enum twain_state {
	TWAIN_STATE_IDLE = 0,
	TWAIN_STATE_DATA_ABORT,
	TWAIN_STATE_RESET,
	TWAIN_STATE_INTERFACE_CHANGE,
	TWAIN_STATE_CONFIG_CHANGE,
	TWAIN_STATE_DISCONNECT,
	TWAIN_STATE_EXIT,
	TWAIN_STATE_TERMINATED,
};

enum queue_id {
	QUEUE_ID_PREVIEW_FULL,
	QUEUE_ID_EMPTY,
	QUEUE_ID_IMGBULK_FULL,
};

struct img_buf {
	int					index;
	dma_addr_t			dma;
	spinlock_t			lock;
	void 				*buf;
	size_t 				boff;
	size_t 				bsize;
	volatile enum buf_state	  	state;
	struct usb_request	*preview_req;  /* use for send preview data */
	struct usb_request	*in_bulk_req; /* use for send raw/bmp data */
	struct list_head	buf_node;
};

struct twain_dev {
	struct usb_gadget	*gadget;	/* slave USB device */
	struct usb_request	*ctrlreq;	/*for control responses*/

	atomic_t			busy;		/*1 if opened*/

	struct usb_ep		*in_bulk_ep;		/* Send image data to host */
	unsigned int		in_bulk_ep_enabled;
	struct usb_ep		*preview_ep;	/* Send preview picture to host */
	unsigned int		preview_ep_enabled;
	struct usb_ep		*incmd_ep;	/* Send cmd/ack to host */
	unsigned int		incmd_ep_enabled;
	struct usb_ep		*outcmd_ep;	/* Get cmd from host */
	unsigned int		outcmd_ep_enabled;
	struct completion	incmd_wqh; /*device to host->write*/
	struct completion	outcmd_wqh;/*host to device->read*/
	struct cdev			cdev;		/* char device */
	struct semaphore	sem;		/* semaphore for this device */
	spinlock_t			lock;
	volatile enum twain_state	state;

	struct img_buf		imgbuf[NUM_BUF_DEF];	/* image buffers */
	struct imgbuf_req	bufinfo;				/* image buffer info */
	struct list_head	empty_queue; /* TWAINC_DQBU: Get buf from queue */
	struct list_head	preview_queue; /* TWAINC_QBUF: Set buf to full queue */
	struct list_head	bulk_queue;/* TWAINC_QIMGBUF: Set buf to img queue*/

	/* thread: use for send image data to host */
	wait_queue_head_t	thread_wqh;
	int					thread_wakeup_needed;
	struct completion	thread_notifier;
	int					thread_pid;
	struct task_struct	*thread_task;
	sigset_t			thread_signal_mask;

	unsigned long		atomic_bitflags;
#define     REGISTERED			0
#define     CLEAR_BULK_HALTS	1
#define     SUSPENDED			2
	unsigned int		running : 1;
	u8					config, new_config;

};


static void raise_exception(struct twain_dev *dev, enum twain_state state);
static void twain_cdev_cleanup(struct twain_dev *dev);
#define xprintk(d,level,fmt,args...) \
	dev_printk(level , &(d)->gadget->dev , fmt , ## args)

#ifdef DEBUG
#define DBG(dev,fmt,args...) \
	xprintk(dev , KERN_DEBUG , fmt , ## args)
#else
#define DBG(dev,fmt,args...) \
	do { } while (0)
#endif /* DEBUG */

#ifdef VERBOSE
#define VDBG	DBG
#else
#define VDBG(dev,fmt,args...) \
	do { } while (0)
#endif /* VERBOSE */

#define ERROR(dev,fmt,args...) \
	xprintk(dev , KERN_ERR , fmt , ## args)
#define WARN(dev,fmt,args...) \
	xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
	xprintk(dev , KERN_INFO , fmt , ## args)


/*
 * if it's nontzero, autoresume says how many seconds to wait
 * before trying to wake up the host after suspend.
 */
static unsigned autoresume = 0;
module_param (autoresume, uint, 0);

#define DRIVER_VENDOR_NUM	0x7ac0		/* Insighten */
#define DRIVER_PRODUCT_NUM	0x1302		/* Linux-USB "Gadget Twain" */


/*
 * DESCRIPTORS ... most are static, but strings and (full)
 * configuration descriptors are built on demand.
 */

#define STRING_MANUFACTURER		0x11
#define STRING_PRODUCT			42
#define STRING_SERIAL			101
#define STRING_TWAIN		250
#define STRING_LOOPBACK			251

/*
 * This device advertises two configurations; these numbers work
 * on a pxa250 as well as more flexible hardware.
 */
#define	CONFIG_VALUE	1

static struct usb_device_descriptor
device_desc = {
	.bLength =		sizeof device_desc,
	.bDescriptorType =	USB_DT_DEVICE,

	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,

	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
	.iManufacturer =	STRING_MANUFACTURER,
	.iProduct =		STRING_PRODUCT,
	.iSerialNumber =	STRING_SERIAL,
	.bNumConfigurations =	1,
};

static struct usb_config_descriptor
twain_usb_config = {
	.bLength =		sizeof twain_usb_config,
	.bDescriptorType =	USB_DT_CONFIG,

	/* compute wTotalLength on the fly */
	.bNumInterfaces =	1,
	.bConfigurationValue =	CONFIG_VALUE,
	.iConfiguration =	STRING_TWAIN,
	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
	.bMaxPower =		1,	/* self-powered */
};

static struct usb_otg_descriptor
otg_descriptor = {
	.bLength =		sizeof otg_descriptor,
	.bDescriptorType =	USB_DT_OTG,

	.bmAttributes =		USB_OTG_SRP,
};

/* one interface in each configuration */

static const struct usb_interface_descriptor
twain_usb_intf = {
	.bLength =		sizeof twain_usb_intf,
	.bDescriptorType =	USB_DT_INTERFACE,

	.bNumEndpoints =	4,
	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
	.iInterface =		STRING_TWAIN,
};


/*
 * usb 2.0 devices need to expose both high speed and full speed
 * descriptors, unless they only run at full speed.
 *
 * that means alternate endpoint descriptors (bigger packets)
 * and a "device qualifier" ... plus more construction options
 * for the config descriptor.
 */

/* endpoint use for jpeg preview */
static struct usb_endpoint_descriptor
hs_preview_desc = {
	.bLength = USB_DT_ENDPOINT_SIZE,
	.bDescriptorType = USB_DT_ENDPOINT,
	
	.bEndpointAddress = USB_DIR_IN,
	.bmAttributes	= USB_ENDPOINT_XFER_BULK,
	.wMaxPacketSize =	__constant_cpu_to_le16(512),
//	.bInterval		= 1,
};

/* endpoint use for send raw/bmp data */
static struct usb_endpoint_descriptor
hs_in_bulk_desc = {
	.bLength = USB_DT_ENDPOINT_SIZE,
	.bDescriptorType = USB_DT_ENDPOINT,
	
	.bEndpointAddress = USB_DIR_IN,
	.bmAttributes	= USB_ENDPOINT_XFER_BULK,
	.wMaxPacketSize =	__constant_cpu_to_le16(512),
//	.bInterval		= 1,
};

static struct usb_endpoint_descriptor
hs_outcmd_desc = {
	.bLength =		USB_DT_ENDPOINT_SIZE,
	.bDescriptorType =	USB_DT_ENDPOINT,
	
	.bEndpointAddress = USB_DIR_OUT,
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
};

static struct usb_endpoint_descriptor
hs_incmd_desc = {
	.bLength =		USB_DT_ENDPOINT_SIZE,
	.bDescriptorType =	USB_DT_ENDPOINT,
	
	.bEndpointAddress = USB_DIR_IN,
	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
};

static struct usb_qualifier_descriptor
dev_qualifier = {
	.bLength =		sizeof dev_qualifier,
	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,

	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,

	.bNumConfigurations =	1,
};

static const struct usb_descriptor_header *hs_twain_function [] = {
	(struct usb_descriptor_header *) &otg_descriptor,
	(struct usb_descriptor_header *) &twain_usb_intf,
	(struct usb_descriptor_header *) &hs_outcmd_desc,
	(struct usb_descriptor_header *) &hs_incmd_desc,
	(struct usb_descriptor_header *) &hs_preview_desc,
	(struct usb_descriptor_header *) &hs_in_bulk_desc,
	NULL,
};

static char				manufacturer [50];
static char				serial []="0123456789,0123456789,0123456789";

/* static strings, in UTF-8 */
static struct usb_string		strings [] = {
	{ STRING_MANUFACTURER, manufacturer, },
	{ STRING_PRODUCT, longname, },
	{ STRING_SERIAL, serial, },
	{ STRING_TWAIN, twain_protocol_name, },
	{  }			/* end of list */
};

static struct usb_gadget_strings	stringtab = {
	.language	= 0x0409,	/* en-us */
	.strings	= strings,
};

static int sleep_thread(struct twain_dev *dev)
{
	int rc;

	rc = wait_event_interruptible(dev->thread_wqh,
			dev->thread_wakeup_needed);
	dev->thread_wakeup_needed = 0;
/*	if( current->flags & PF_FREEZE ) {
		refrigerator(PF_FREEZE);
	}
	*/
	return (rc ? -EINTR : 0);
}
static void wakeup_thread(struct twain_dev *dev)
{
	dev->thread_wakeup_needed = 1;
	wake_up_all(&dev->thread_wqh);
}
static int
config_buf (struct usb_gadget *gadget,
		u8 *buf, u8 type, unsigned index)
{
	int				len;
	const struct usb_descriptor_header **function;

	/* two configurations will always be index 0 and index 1 */

	function = hs_twain_function;
	/* for now, don't advertise srp-only devices */
	if (!gadget->is_otg)
		function++;

	len = usb_gadget_config_buf (&twain_usb_config,
			buf, EP0_BUFSIZ, function);
	if (len < 0)
		return len;
	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
	return len;
}


static struct usb_request *
alloc_ep_req (struct usb_ep *ep, unsigned length)
{
	struct usb_request	*req;

	req = usb_ep_alloc_request (ep, GFP_ATOMIC);
	if (req) {
		req->length = length;
		req->buf = usb_ep_alloc_buffer (ep, length,
				&req->dma, GFP_ATOMIC);
		if (!req->buf) {
			usb_ep_free_request (ep, req);
			req = NULL;
		}
	}
	return req;
}

static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
{
	if (req->buf)
		usb_ep_free_buffer(ep, req->buf, req->dma, req->length);
	usb_ep_free_request(ep, req);
}

static void preview_complete(struct usb_ep *ep, struct usb_request *req)
{
		struct twain_dev *dev = twdev;
		struct img_buf *img = NULL;
		
		img = (struct img_buf *)req->context;

		if( req->status || req->actual != req->length ) {
			DBG(dev, "%s-->%d, %u/%u\n", __func__,
					req->status, req->actual, req->length);
		}
		if( req->status == -ECONNRESET ) {
			usb_ep_fifo_flush(ep);
		}
		spin_lock(&dev->lock);
		img->state = BUF_STATE_EMPTY;
		list_add_tail(&img->buf_node, &dev->empty_queue);
		spin_unlock(&dev->lock);
		wakeup_thread(dev);
}
/* same as preview_complete ?? */
static void in_bulk_complete(struct usb_ep *ep, struct usb_request *req)
{
		struct twain_dev *dev = twdev;
		struct img_buf *img = NULL;
		
		img = (struct img_buf *)req->context;

		if( req->status || req->actual != req->length ) {
			DBG(dev, "%s-->%d, %u/%u\n", __func__,
					req->status, req->actual, req->length);
		}
		if( req->status == -ECONNRESET ) {
			usb_ep_fifo_flush(ep);
		}
		spin_lock(&dev->lock);
		img->state = BUF_STATE_EMPTY;
		list_add_tail(&img->buf_node, &dev->empty_queue);
		spin_unlock(&dev->lock);
		wakeup_thread(dev);
}

/* if there is only one request in the queue, there'll always be an
 * irq delay between end of one request and start of the next.
 * that prevents using hardware dma queues.
 */
static void read_cmd_complete (struct usb_ep *ep, struct usb_request *req)
{
	struct twain_dev	*dev = ep->driver_data;
	int		status = req->status;

	switch (status) {

	case REQUEST_OK: 			/* normal completion? */
		break;
	/* this endpoint is normally active while we're configured */
	case -ECONNABORTED: 	/* hardware forced ep reset */
	case -ECONNRESET:		/* request dequeued */
	case -ESHUTDOWN:		/* disconnect from host */
		VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
				req->actual, req->length);
		free_ep_req (ep, req);
		return;

	case -EOVERFLOW:/* buffer overrun on read means that
					 * we didn't provide a big enough
					 * buffer.
					 */
	default:
#if 1
		DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
				status, req->actual, req->length);
#endif
	case -EREMOTEIO:		/* short read */
		break;
	}
	complete(&dev->outcmd_wqh); /* notify reader */
}

static void write_cmd_complete (struct usb_ep *ep, struct usb_request *req)
{
	struct twain_dev	*dev = ep->driver_data;
	int		status = req->status;

	switch (status) {

	case REQUEST_OK: 			/* normal completion? */
		break;
	/* this endpoint is normally active while we're configured */
	case -ECONNABORTED: 	/* hardware forced ep reset */
	case -ECONNRESET:		/* request dequeued */
	case -ESHUTDOWN:		/* disconnect from host */
		VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
				req->actual, req->length);
		free_ep_req (ep, req);
		return;

	case -EOVERFLOW:/* buffer overrun on read means that
					 * we didn't provide a big enough
					 * buffer.
					 */
	default:
#if 1
		DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
				status, req->actual, req->length);
#endif
	case -EREMOTEIO:		/* short write */
		break;
	}
	complete(&dev->incmd_wqh); /* notify writer */
}


static struct usb_request *
read_cmd_start(struct usb_ep *ep, unsigned int len)
{
	struct usb_request *req;
	int status;
	printk("in %s\n",__FUNCTION__);
	req = alloc_ep_req(ep, len);
	if (!req)
		return NULL;
	memset(req->buf, 0, req->length);
	req->complete = read_cmd_complete; 
	req->context = (struct usb_request *)req;
	status = usb_ep_queue(ep, req, GFP_ATOMIC); 
	if (status) {
		printk("start %s --> %d\n", ep->name, status);
		free_ep_req(ep, req);
		req = NULL;
	}
	return req;

}
static int
enable_endpoints (struct twain_dev *dev)
{
	int			result = 0;
	struct usb_ep		*ep;
	struct usb_gadget	*gadget = dev->gadget;

	gadget_for_each_ep (ep, gadget) {
		const struct usb_endpoint_descriptor	*d;

		/* one endpoint for read cmd */
		if (strcmp (ep->name, EP_OUTCMD_NAME) == 0) {
			d = &hs_outcmd_desc;
			result = usb_ep_enable(ep, d);
			if (result == 0) {
				ep->driver_data = dev;
				dev->outcmd_ep = ep;
				dev->outcmd_ep_enabled = 1;
				continue;
			}
		/* one endpoint for write cmd */
		}else if( strcmp(ep->name, EP_INCMD_NAME) == 0 ) {
			d = &hs_incmd_desc;
			result = usb_ep_enable(ep, d);
			if( result == 0 ) {
				ep->driver_data = dev;
				dev->incmd_ep = ep;
				dev->incmd_ep_enabled = 1;
				continue;
			}
		/* one endpoint for send preview picture */
		}else if( strcmp(ep->name, EP_PREVIEW) == 0 ) {
			d = &hs_preview_desc;
			result = usb_ep_enable(ep, d);
			if( result == 0 ) {
				ep->driver_data = dev;
				dev->preview_ep = ep;
				dev->preview_ep_enabled = 1;
				continue;
			}
		/* one endpoint for send raw/bmp data to the host */
		} else if( strcmp(ep->name, EP_INBULK_NAME) == 0 ) {
			d = &hs_in_bulk_desc;
			result = usb_ep_enable(ep, d);
			if( result == 0 ) {
				ep->driver_data = dev;
				dev->in_bulk_ep = ep;
				dev->in_bulk_ep_enabled = 1;
				continue;
			}
		} else 
			continue; /* ignore any other endpoints */

		/* stop on error */
		ERROR (dev, "can't start %s, result %d\n", ep->name, result);
		break;
	}
	if (result == 0)
		DBG (dev, "Set up End Point OK!\n");
	/* caller is responsible for cleanup on error */

	return result;
}
static void disable_endpoints(struct twain_dev *dev)
{

	INFO (dev, "disable endpoints\n");

	/* just disable endpoints, forcing completion of pending i/o.
	 * all our completion handlers free their requests in this case.
	 */

	if ( dev->outcmd_ep_enabled ) {	/* Get cmd data from end point */
		usb_ep_disable (dev->outcmd_ep);
		dev->outcmd_ep = NULL;
		dev->outcmd_ep_enabled = 0;
	}
	if( dev->incmd_ep_enabled ) {
		usb_ep_disable(dev->incmd_ep);
		dev->incmd_ep = NULL;
		dev->incmd_ep_enabled = 0;
	}
	if( dev->preview_ep_enabled ) {
		usb_ep_disable(dev->preview_ep);
		dev->preview_ep = NULL;
		dev->preview_ep_enabled = 0;
	}
	if( dev->in_bulk_ep_enabled ) {
		usb_ep_disable(dev->in_bulk_ep);
		dev->in_bulk_ep = NULL;
		dev->in_bulk_ep_enabled = 0;
	}

}

static int alloc_request(struct usb_ep *ep, struct usb_request **preq)
{
	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if( *preq ) {
		return 0;
	}
	return -ENOMEM;
}

static int do_set_interface(struct twain_dev *dev, int altsetting)
{
	int rc = 0;
	int i;

	if( dev->running ) {
		DBG(dev, "reset interface\n");
	}
reset:
	/* Deallocate the requests */
	for( i=0 ; i<NUM_BUF_DEF ; i++ ) {
		struct img_buf *img = &dev->imgbuf[i];
		if( img->preview_req ) {
			usb_ep_free_request(dev->preview_ep, img->preview_req);
			img->preview_req = NULL;
		}
		if( img->in_bulk_req ) {
			usb_ep_free_request(dev->in_bulk_ep, img->in_bulk_req);
			img->in_bulk_req = NULL;
		}
	}
	/* Disable the endpoints */
	disable_endpoints(dev);

	dev->running = 0;
	if( altsetting < 0 ) {
		return rc;
	}

	/* Enable the endpoints */
	enable_endpoints(dev);

	/* Allocate the requests */
	for( i=0 ; i<NUM_BUF_DEF ; i++ ) {
		struct img_buf	*img = &dev->imgbuf[i];
		if( (rc = alloc_request(dev->preview_ep, &img->preview_req)) != 0) {
			goto reset;
		}
		if( (rc = alloc_request(dev->in_bulk_ep, &img->in_bulk_req)) != 0 ) {
			goto reset;
		}
		img->preview_req->buf = img->in_bulk_req->buf = img->buf;
		img->preview_req->dma = img->in_bulk_req->dma = img->dma;
		img->preview_req->context = img->in_bulk_req->context = img;
		img->preview_req->complete = preview_complete;
		img->in_bulk_req->complete = in_bulk_complete;
	}

	dev->running = 1;

	return 0;
}
static int
do_set_config (struct twain_dev *dev, u8 new_config)
{
	struct usb_gadget	*gadget = dev->gadget;
	int rc = 0;

	/* Disable the interface */
	if( dev->config != 0 ) {
		dev->config = 0;
		rc = do_set_interface(dev, -1);
	}

	if (new_config != 0) {
		dev->config = new_config;
		if( (rc=do_set_interface(dev, 0)) != 0 ) {
			dev->config = 0;
		} else {
			char *speed;

			switch (gadget->speed) {
				case USB_SPEED_LOW:		speed = "low"; break;
				case USB_SPEED_FULL:	speed = "full"; break;
				case USB_SPEED_HIGH:	speed = "high"; break;
				default: 				speed = "?"; break;
			}

			INFO (dev, "%s speed config: %s\n", speed,
					twain_protocol_name);
		}
	}

	return rc;
}


static void twain_gadget_setup_complete (struct usb_ep *ep, struct usb_request *req)
{

	if (req->status || req->actual != req->length)
		DBG ((struct twain_dev *) ep->driver_data,
				"setup complete --> %d, %d/%d\n",
				req->status, req->actual, req->length);
}

/*
 * The setup() callback implements all the ep0 functionality that's
 * not handled lower down, in hardware or the hardware driver (like
 * device and endpoint feature flags, and their status).  It's all
 * housekeeping for the gadget function we're implementing.  Most of
 * the work is in config-specific setup.
 */
static int
twain_gadget_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{
	struct twain_dev		*dev = get_gadget_data (gadget);
	struct usb_request	*req = dev->ctrlreq;
	int			value = -EOPNOTSUPP;
	u16			wIndex = le16_to_cpu(ctrl->wIndex);
	u16			wValue = le16_to_cpu(ctrl->wValue);
	u16			wLength = le16_to_cpu(ctrl->wLength);

	DBG (dev,"req%02x.%02x v%04x i%04x l%d\n",
			ctrl->bRequestType, ctrl->bRequest,
			wValue, wIndex, wLength);


	/* usually this stores reply data in the pre-allocated ep0 buffer,
	 * but config change events will reconfigure hardware.
	 */
	req->zero = 0;
	switch (ctrl->bRequest) {

		case USB_REQ_GET_DESCRIPTOR:
			if (ctrl->bRequestType != USB_DIR_IN)
				goto unknown;
			switch (wValue >> 8) {

				case USB_DT_DEVICE:
					value = min (wLength, (u16) sizeof device_desc);
					memcpy (req->buf, &device_desc, value);
					break;
				case USB_DT_DEVICE_QUALIFIER:
					if (!gadget->is_dualspeed)
						break;
					value = min (wLength, (u16) sizeof dev_qualifier);
					memcpy (req->buf, &dev_qualifier, value);
					break;

				case USB_DT_OTHER_SPEED_CONFIG:
					if (!gadget->is_dualspeed)
						break;
					// FALLTHROUGH
				case USB_DT_CONFIG:
					value = config_buf (gadget, req->buf,
							wValue >> 8,
							wValue & 0xff);
					if (value >= 0)
						value = min (wLength, (u16) value);
					break;
				case USB_DT_STRING:
					/* wIndex == language code.
					 * this driver only handles one language, you can
					 * add string tables for other languages, using
					 * any UTF-8 characters
					 */
					value = usb_gadget_get_string (&stringtab,
							wValue & 0xff, req->buf);
					if (value >= 0)
						value = min (wLength, (u16) value);
					break;
			}
			break;

		case USB_REQ_SET_CONFIGURATION:
			if (ctrl->bRequestType != 0)
				goto unknown;
			if (wValue == CONFIG_VALUE || wValue == 0) {
				dev->new_config = wValue;
				raise_exception(dev, TWAIN_STATE_CONFIG_CHANGE);
				value = 0;
			}
			break;
		case USB_REQ_GET_CONFIGURATION:
			if (ctrl->bRequestType != USB_DIR_IN)
				goto unknown;
			*(u8 *)req->buf = dev->config;
			value = min (wLength, (u16) 1);
			break;

			/* until we add altsetting support, or other interfaces,
			 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
			 * and already killed pending endpoint I/O.
			 */
		case USB_REQ_SET_INTERFACE:
			if (ctrl->bRequestType != USB_RECIP_INTERFACE)
				goto unknown;
			spin_lock (&dev->lock);
			if (wIndex == 0 && wValue == 0) {
				/* resets interface configuration, forgets about
				 * previous transaction state (queued bufs, etc)
				 * and re-inits endpoint state (toggle etc)
				 * no response queued, just twain status == success.
				 * if we had more than one interface we couldn't
				 * use this "reset the config" shortcut.
				 */
				raise_exception(dev, TWAIN_STATE_INTERFACE_CHANGE);
				value = 0;
			}
			spin_unlock (&dev->lock);
			break;
		case USB_REQ_GET_INTERFACE:
			if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
				goto unknown;
			if (wIndex != 0) {
				value = -EDOM;
				break;
			}
			*(u8 *)req->buf = 0;
			value = min (wLength, (u16) 1);
			break;

			/*
			 * These are the same vendor-specific requests supported by
			 * Intel's USB 2.0 compliance test devices.  We exceed that
			 * device spec by allowing multiple-packet requests.
			 */
		case 0x5b:	/* control WRITE test -- fill the buffer */
			if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
				goto unknown;
			if (wValue || wIndex)
				break;
			/* just read that many bytes into the buffer */
			if (wLength > EP0_BUFSIZ)
				break;
			value = wLength;
			break;
		case 0x5c:	/* control READ test -- return the buffer */
			if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
				goto unknown;
			if (wValue || wIndex)
				break;
			/* expect those bytes are still in the buffer; send back */
			if (wLength > EP0_BUFSIZ
					|| wLength != req->length)
				break;
			value = wLength;
			break;

		default:
unknown:
			VDBG (dev,
					"unknown control req%02x.%02x v%04x i%04x l%d\n",
					ctrl->bRequestType, ctrl->bRequest,
					wValue, wIndex, wLength);
	}

	/* respond with data transfer before status phase? */
	if (value >= 0) {
		req->length = value;
		req->zero = value < wLength
			&& (value % gadget->ep0->maxpacket) == 0;
		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
		if (value < 0) {
			DBG (dev, "ep_queue --> %d\n", value);
			req->status = 0;
			twain_gadget_setup_complete (gadget->ep0, req);
		}
	}

	/* device either stalls (value < 0) or reports success */
	return value;
}

static void
twain_gadget_disconnect (struct usb_gadget *gadget)
{
	struct twain_dev		*dev = get_gadget_data (gadget);
	
	printk(KERN_ALERT "fun = %s line= %d\n", __func__, __LINE__);

	raise_exception(dev, TWAIN_STATE_DISCONNECT);
}

static void twain_cdev_cleanup(struct twain_dev *dev)
{
	dev_t	cdev_no;
	
	cdev_no = MKDEV(twain_major, 0);
	unregister_chrdev_region(cdev_no, 1);
	cdev_del(&dev->cdev);
}

void inline 
free_reserved_pages(unsigned long bufaddr, unsigned long bufsize)
{
	unsigned long size;
	unsigned long addr;
	if( !bufaddr ) {
		return;
	}
	addr = bufaddr;
	size = bufsize;
	while( size > 0 ) {
		ClearPageReserved(virt_to_page(addr));
		addr += PAGE_SIZE;
		size -= PAGE_SIZE;
	}
	free_pages(bufaddr, get_order(bufsize));
}

/* will invoke when vm_close or mmap free */
static void buffers_free(struct twain_dev *dev)
{
	int i;
	struct img_buf	*img = NULL;
	
	down(&dev->sem);
	for( i=0 ; i < NUM_BUF_DEF ; i++ ) {
		img = &dev->imgbuf[i];
		if( img->buf ) {
			free_reserved_pages((unsigned long)img->buf,img->bsize);
			img->buf = NULL;
			memset(img, 0, sizeof(struct img_buf));
		} else {
			continue;
		}
	}
	dev->bufinfo.buf_num = 0;
	dev->bufinfo.buf_size = 0;
	up(&dev->sem);
	
}

static int buffers_reset(struct twain_dev *dev)
{
	int i;
	struct img_buf *b = NULL;
	
	if( dev->preview_ep_enabled ) {
		usb_ep_fifo_flush(dev->preview_ep);
	}
	if( dev->incmd_ep_enabled ) {
		usb_ep_fifo_flush(dev->incmd_ep);
	}
	if( dev->outcmd_ep_enabled ) {
		usb_ep_fifo_flush(dev->outcmd_ep);
	}
	if( dev->in_bulk_ep_enabled ) {
		usb_ep_fifo_flush(dev->in_bulk_ep);
	}

	do_set_interface(dev, 0);
	spin_lock(&dev->lock);
	list_del_init(&dev->preview_queue);
	list_del_init(&dev->bulk_queue);
	list_del_init(&dev->empty_queue);
	spin_unlock(&dev->lock);
	for( i=0 ; i<NUM_BUF_DEF ; i++ ) {
		b = &dev->imgbuf[i];
	//	usb_ep_dequeue (dev->preview_ep, b->preview_req);
		if( b->buf ) {
			spin_lock(&dev->lock);
			b->state = BUF_STATE_EMPTY;
			INIT_LIST_HEAD(&b->buf_node);
			list_add_tail(&b->buf_node, &dev->empty_queue);
			spin_unlock(&dev->lock);
		}
	}

	return 0;
	
}
static int buffers_alloc(struct twain_dev *dev)
{
	int i;
	int size = PAGE_ALIGN(SIZ_BUF_DEF);
	void *mem;

	down(&dev->sem);
	for( i = 0 ; i<NUM_BUF_DEF ; i++ ) {
		struct img_buf *img = &dev->imgbuf[i];
		mem = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, 
				get_order(size));
		if( mem ) {
			unsigned long adr = (unsigned long)mem;
			unsigned int s = PAGE_SIZE << (get_order(size));
			while( s > 0 ) {
				SetPageReserved(virt_to_page(adr));
				adr += PAGE_SIZE;
				s	-= PAGE_SIZE;
			}
			img->buf = (char*) mem;
		} else {
			while( --i >= 0 ) {
				img = &dev->imgbuf[i];
				free_reserved_pages((unsigned long)img->buf, size);
			}
			up(&dev->sem);
			return -ENOMEM;
		}
		img->index = i;
		img->bsize = PAGE_ALIGN(size);
		img->dma = DMA_ADDR_INVALID;
		img->boff = virt_to_phys(img->buf);
		img->state = BUF_STATE_EMPTY;
		INIT_LIST_HEAD(&img->buf_node);
		list_add_tail(&img->buf_node, &dev->empty_queue);
	}
	dev->bufinfo.buf_num = i;
	dev->bufinfo.buf_size = size;
	up(&dev->sem);

	return 0;
}

static int buffers_reqbufs(struct twain_dev *dev, struct imgbuf_req *req)
{
	memcpy(req, &dev->bufinfo, sizeof(struct imgbuf_req));
	return 0;
}

static int buffer_query(struct twain_dev *dev, struct imgbuf_info *query)
{
	struct img_buf *img = NULL;
	if(unlikely(!query || query->index > dev->bufinfo.buf_num)) {
		return -EINVAL;
	}
	img = &dev->imgbuf[query->index];
	if( unlikely(!img) ) {
		return -EINVAL;
	}
	query->length = img->bsize;
	query->offset = img->boff;

	return 0;
}

static struct img_buf *buffer_prepear(struct twain_dev *dev, enum queue_id qid)
{
	struct img_buf *img;
	struct list_head *ptr;
	struct list_head *queue;

	if( unlikely(!dev) ) {
		return NULL;
	}
	switch ( qid ) {
		case QUEUE_ID_PREVIEW_FULL :
			queue = &dev->preview_queue;
			break;
		case QUEUE_ID_EMPTY :
			queue = &dev->empty_queue;
			break;
		case QUEUE_ID_IMGBULK_FULL :
			queue = &dev->bulk_queue;
			break;
		default :
			return NULL;
			break;
	}

	spin_lock(&dev->lock);
		list_for_each(ptr, queue) {
		img = list_entry(ptr, struct img_buf, buf_node);
		if( img && img->buf) {
			list_del(ptr); /* remove from queue */
			spin_unlock(&dev->lock);
			printk("##imginfo## index=%d;bufaddr=%p, bsize=0x%x, boff=0x%x\n",
					img->index,img->buf, img->bsize, img->boff);
			return img;
		}
	}
	spin_unlock(&dev->lock);
	return NULL;
}

static int buffer_dequeue(struct twain_dev *dev, struct imgbuf_info *req)
{
	struct img_buf *img = NULL;

	if( unlikely(!req )) {
		return -EINVAL;
	}
retry:
	img = buffer_prepear(dev, QUEUE_ID_EMPTY);
	if( !img || !img->buf) {
	//	sleep_thread(dev);
		goto retry;
	}
	spin_lock(&img->lock);
	req->index = img->index;
	req->length = img->bsize;
	req->offset = img->boff;
	img->state = BUF_STATE_IDLE;
	spin_unlock(&img->lock);

	return 0;
	
}

static int buffer_queue(struct twain_dev *dev, struct imgbuf_info *req)
{
	int flags;
	struct img_buf *img = &dev->imgbuf[req->index];

	if( unlikely(!dev || !req || 
				req->index > dev->bufinfo.buf_num ) ) {
		return -EINVAL;
	}
	spin_lock_irqsave(&dev->lock, flags);
	img->state = BUF_STATE_FULL;
	/* add to full queue and will send out via preview_ep and ring back empt queue*/
	img->preview_req->length = req->length;
	list_add_tail(&img->buf_node, &dev->preview_queue); 
	spin_unlock_irqrestore(&dev->lock, flags);

	wakeup_thread(dev);

	return 0;
}
static int buffer_queue_bulk(struct twain_dev *dev, struct imgbuf_info *req)
{
	int flags;
	struct img_buf *img = &dev->imgbuf[req->index];

	if( unlikely(!dev || !req || 
				req->index > dev->bufinfo.buf_num)) {
		return -EINVAL;
	}
	spin_lock_irqsave(&dev->lock, flags);
	img->state = BUF_STATE_FULL;
	img->in_bulk_req->length = req->length;
	list_add_tail(&img->buf_node, &dev->bulk_queue);
	spin_unlock_irqrestore(&dev->lock, flags);

	wakeup_thread(dev);
	return 0;
}
/*use for send preview data and raw/bmp data*/
static void start_transfer(struct twain_dev *dev, enum queue_id qid )
{

	struct img_buf *img = NULL;
	struct usb_ep *ep = NULL;
	struct usb_request *req = NULL;
	int rc;

	if( unlikely(!dev) ) {
		return;
	}
	img = buffer_prepear(dev, qid);
	if( !img ) {
		printk(KERN_ALERT "enter %s->%d###\n", __func__, __LINE__);
		return;
	}
	if( img->state == BUF_STATE_BUSY ) {
		return;
	} else {
		spin_lock(&dev->lock);
		img->state = BUF_STATE_BUSY;
		spin_unlock(&dev->lock);
	}
	if( qid == QUEUE_ID_PREVIEW_FULL ) {
		ep = dev->preview_ep;
		req = img->preview_req;
	} else if( qid == QUEUE_ID_IMGBULK_FULL ) {
		ep = dev->in_bulk_ep;
		req = img->in_bulk_req;
	} else {
		return;
	}
	if( !ep || !req ) {
		printk(KERN_ALERT "ERRR %s->%d###imgindex=%d\n", __func__, __LINE__, img->index);
	}
	printk(KERN_ALERT "%d###req->length=%d\n", __LINE__, req->length);

	rc = usb_ep_queue(ep, req, GFP_ATOMIC);
	if( rc ) { /* some thing wrong! */
		spin_lock(&dev->lock);
		img->state = BUF_STATE_EMPTY;
		list_add_tail(&img->buf_node, &dev->empty_queue);
		spin_unlock(&dev->lock);
	}

}
static int twain_chr_ioctl(struct inode *inode, struct file *file,
			unsigned int cmd, unsigned long arg)
{
	struct twain_dev *dev = file->private_data;
	int retval;
	struct imgbuf_req req;
	struct imgbuf_info info;

	switch ( cmd ) {
		case TWAINC_REQBUFS :
#if 0
			if( copy_from_user(&req, (struct imgbuf_req *)arg,
						sizeof(struct imgbuf_req)) ) {
				return -EINVAL;
			}
#endif
			INFO(dev, "Kerne : TWAINC_REQBUFS req->buf_num = %d\n"
					  "req->buf_size = %d\n",req.buf_num, req.buf_size );
			retval = buffers_reqbufs(dev, &req);
			if( retval < 0 ) {
				return retval;
			}
			if( copy_to_user((struct imgbuf_req*)arg, &req,
						sizeof(struct imgbuf_req)) ) {
				return -EINVAL;
			}
			break;
		case TWAINC_QUERYBUF :
			if( copy_from_user(&info, (struct imgbuf_info *)arg,
						sizeof(struct imgbuf_info)) ) {
				return -EINVAL;
			}
			INFO(dev, "Kerne : TWAINC_QUERYBUF\n");
			retval = buffer_query(dev, &info);
			if( retval < 0 ) {
				return retval;
			}
			if( copy_to_user((struct imgbuf_info*)arg, &info,
						sizeof(struct imgbuf_info)) ) {
				return -EINVAL;
			}
			break;
		case TWAINC_QBUF :
			INFO(dev, "Kerne : TWAINC_QBUF\n");
			if( copy_from_user(&info, (struct imgbuf_info *)arg,
						sizeof(struct imgbuf_info))) {
				return -EINVAL;
			}
			retval = buffer_queue(dev, &info);
			if( retval < 0 ) {
				return retval;
			}
#if 0
			if( !list_empty(&dev->preview_queue) ) {
				INFO(dev, "#########transfer########\n");
				start_transfer(dev, QUEUE_ID_PREVIEW_FULL);
			}
#endif
			break;
		case TWAINC_DQBUF :
			INFO(dev, "Kerne : TWAINC_DQBUF\n");
			if( copy_from_user(&info, (struct imgbuf_info *)arg,
						sizeof(struct imgbuf_info))) {
				return -EINVAL;
			}
			retval = buffer_dequeue(dev, &info);
			if( retval < 0 ) {
				return retval;
			}
			if( copy_to_user((struct imgbuf_info*)arg, &info,
						sizeof(struct imgbuf_info)) ) {
				return -EINVAL;
			}
			break;
		case TWAINC_QIMGBUF :
			INFO(dev, "Kerne : TWAINC_QIMGBUF");
			if( copy_from_user(&info, (struct imgbuf_info *)arg,
						sizeof(struct imgbuf_info))) {
				return -EINVAL;
			}
			retval = buffer_queue_bulk(dev, &info);
			if( retval < 0 ) {
				return retval;
			}
			break;
		default :
			return -ESRCH;
	}
	return 0;
}

static int twain_chr_open(struct inode *inode, struct file *file)
{
	struct twain_dev *dev = container_of(inode->i_cdev, struct twain_dev, cdev);
	printk(KERN_NOTICE "twain_chr_open\n");
	file->private_data = dev;

	if( atomic_read(&dev->busy) ) {
		return -EBUSY;
	}
	
//	twain_set_config (dev);
	atomic_set(&dev->busy, 1);

	return 0;
}

static int twain_chr_release(struct inode *inode, struct file *file)
{

	struct twain_dev *dev = container_of(inode->i_cdev, struct twain_dev, cdev);
	printk(KERN_NOTICE "twain_chr_release\n");
	file->private_data = NULL;

	atomic_set(&dev->busy, 0);

	return buffers_reset(twdev);
}

static ssize_t
twain_chr_read(struct file *file, char __user *buf, 
		size_t count, loff_t *f_pos)
{
	struct twain_dev *dev = file->private_data;
	struct usb_ep *outcmd_ep;
	struct usb_request *req = NULL;
	ssize_t ret = 0;

	printk(KERN_NOTICE "twain_chr_read\n");

	outcmd_ep = dev->outcmd_ep;
	if (count < 0) {
		return -EINVAL;
	}
	count = min(count, outbuflen);
	req = read_cmd_start(outcmd_ep, outbuflen);
	if( !req ) {
		return -EFAULT;
	}
	wait_for_completion_interruptible(&dev->outcmd_wqh);
	if( !req->buf) {
		return -EFAULT;
	}
	ret = copy_to_user(buf,req->buf, req->actual);
	if( ret < 0 ) {
		printk(KERN_ALERT "Read Cmd data Wrong\n");
		ret = -EFAULT;
	} else {
		ret = req->actual;
	}

	free_ep_req(outcmd_ep, req); /* finished one cmd and release! */
	return ret;
}
/* write cmd/ack back host */
static struct usb_request *
write_cmd_start(struct usb_ep *ep, const char __user *buf,
		unsigned int len)
{
	struct usb_request *req = NULL;
	int status;
	printk("in %s\n",__FUNCTION__);
	req = alloc_ep_req(ep, len);
	if (!req)
		return NULL;
	memcpy(req->buf, buf, req->length);
	req->complete = write_cmd_complete; 
	status = usb_ep_queue(ep, req, GFP_ATOMIC); 
	if (status) {
		printk("start %s --> %d\n", ep->name, status);
		free_ep_req(ep, req);
		req = NULL;
	}
	return req;

}

static ssize_t 
twain_chr_write(struct file *file, const char __user *buf,
				size_t count, loff_t *offp)
{
	struct twain_dev *dev = file->private_data;
	struct usb_ep *ep;
	struct usb_request *req = NULL;

	ep = dev->incmd_ep;
	if (count < 0) {
		return -EINVAL;
	}
	req = write_cmd_start(ep, buf, count);
	wait_for_completion(&dev->incmd_wqh);
	free_ep_req(ep, req); /* finished one cmd and release! */
	return 0;
}

static int twain_chr_mmap(struct file *file, struct vm_area_struct *vma)
{
	struct twain_dev *dev = twdev;
	unsigned int first;
	struct img_buf *img = NULL;

	down(&dev->sem);
	if( !(vma->vm_flags & VM_WRITE) ) {
		printk(KERN_ERR "%s->%d error\n", __func__, __LINE__);
		goto done;
	}
	if( !(vma->vm_flags & VM_SHARED)) {
		printk(KERN_ERR "%s->%d error\n", __func__, __LINE__);
		goto done;	
	}
	for( first=0 ; first < NUM_BUF_DEF ; first++ ) {
		img = &dev->imgbuf[first];
		if( img->buf == NULL) {
			continue;
		}
		if( img->boff == (vma->vm_pgoff << PAGE_SHIFT) &&
			img->bsize ==(vma->vm_end - vma->vm_start)) {
			break;
		}
	}
	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
	if( io_remap_page_range(vma, vma->vm_start,
				(vma->vm_pgoff << PAGE_SHIFT),
				(vma->vm_end - vma->vm_start),
				vma->vm_page_prot) ) {
		return -EAGAIN;
	}

	vma->vm_flags |= VM_RESERVED | VM_IO;
	
done:
	up(&dev->sem);

	return 0;

}
static struct file_operations twain_chr_fops = {
	.owner = THIS_MODULE,
	.open  = twain_chr_open,
	.read  = twain_chr_read,
	.write = twain_chr_write,
	.ioctl = twain_chr_ioctl,
	.mmap  = twain_chr_mmap,
	.release = twain_chr_release,
};

static struct twain_dev *twain_dev_alloc(void)
{
	struct twain_dev *dev;
	dev = kmalloc(sizeof *dev, SLAB_KERNEL);
	if (!dev)
		return NULL;
	memset (dev, 0, sizeof *dev);

	atomic_set(&dev->busy, 0);
	init_completion(&dev->incmd_wqh);
	init_completion(&dev->outcmd_wqh);
	init_completion(&dev->thread_notifier);
	init_waitqueue_head(&dev->thread_wqh);
	init_MUTEX(&dev->sem);
	INIT_LIST_HEAD(&dev->empty_queue);
	INIT_LIST_HEAD(&dev->preview_queue);
	INIT_LIST_HEAD(&dev->bulk_queue);

	dev->state = TWAIN_STATE_IDLE;

	return dev;
}

static void twain_dev_free(struct twain_dev *dev)
{
	if( dev != NULL ) {
		/* FIXME do other clean */
		memset(dev, 0, sizeof(struct twain_dev));
		kfree(dev);
	}
}

static int twain_cdev_setup(struct twain_dev *dev)
{
	dev_t	cdev_no;
	int		ret = -EINVAL;

	cdev_no = MKDEV(twain_major, 0);
	if( register_chrdev_region(cdev_no, 1, "usb_twain") < 0) {
		return -ENOMEM;
	}
	cdev_init(&dev->cdev, &twain_chr_fops);
	dev->cdev.owner = THIS_MODULE;
	ret = cdev_add(&dev->cdev, cdev_no, 1);
	if( ret < 0 ) {
		ret = -ENOMEM;
		goto fail;
	}
	return 0;
fail:
	unregister_chrdev_region(cdev_no, 1);
	return ret;
}

static int inline exception_in_progress(struct twain_dev *dev)
{
	return (dev->state > TWAIN_STATE_IDLE);
}


static void raise_exception(struct twain_dev *dev, enum twain_state state)
{
	unsigned long flags;
	struct task_struct *thread_task;
	
	spin_lock_irqsave(&dev->lock, flags);
	if( dev->state <= state ) {
		dev->state = state;
		thread_task = dev->thread_task;
		if( thread_task ) {
			send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task);
		}
	}
	spin_unlock_irqrestore(&dev->lock, flags);
}


static void handle_exception(struct twain_dev *dev_)
{
	siginfo_t	info;
	int sig;
	int i;
	int rc;
	struct img_buf *imgbuf;
	int active_buf_num;
	struct twain_dev *dev = dev_;
	enum twain_state	old_state;
	u8		new_config;

	for( ;  ; ) {
		sig = dequeue_signal_lock(current, &dev->thread_signal_mask, &info);
		if( !sig ) {
			break;
		}
		if( sig != SIGUSR1 ) {
			if( dev->state < TWAIN_STATE_EXIT ) {
				DBG(dev, "Main thread exiting on signal\n");
				raise_exception(dev, TWAIN_STATE_EXIT);
			}
		}
	}
	/* dequeue all usb request */
	for( i=0 ; i<NUM_BUF_DEF ; i++ ) {
		imgbuf = &dev->imgbuf[i];
		if( imgbuf->buf ) {
			if( imgbuf->state == BUF_STATE_BUSY ) {
				usb_ep_dequeue(dev->preview_ep, imgbuf->preview_req);
			}
		}
	}

	for(  ;  ;  ) {
		active_buf_num = 0;
		for( i=0 ; i<NUM_BUF_DEF ; i++ ) {
			imgbuf = &dev->imgbuf[i];
			if( imgbuf->state == BUF_STATE_BUSY ) {
				active_buf_num++;
				break;
			}
		}
		if( active_buf_num == 0 ) {
			break;
		}
		if( sleep_thread(dev) ) {
			return;
		}
	}

	/* clear out the controller's fifos */
	if( dev->preview_ep_enabled ) {
		usb_ep_fifo_flush(dev->preview_ep);
	}
	if( dev->incmd_ep_enabled ) {
		usb_ep_fifo_flush(dev->incmd_ep);
	}
	if( dev->outcmd_ep_enabled ) {
		usb_ep_fifo_flush(dev->outcmd_ep);
	}
	if( dev->in_bulk_ep_enabled ) {
		usb_ep_fifo_flush(dev->in_bulk_ep);
	}

	/* reset all the buffers state */
	for( i=0 ; i<NUM_BUF_DEF ; i++ ) {
		imgbuf = &dev->imgbuf[i];
		imgbuf->state = BUF_STATE_EMPTY;
	}

	new_config = dev->new_config;
	old_state = dev->state;
	dev->state = TWAIN_STATE_IDLE;
	switch ( old_state ) {
		case TWAIN_STATE_TERMINATED :
		case TWAIN_STATE_EXIT :
			do_set_config(dev, 0);
			spin_lock(&dev->lock);
			dev->state = TWAIN_STATE_TERMINATED;
			spin_unlock(&dev->lock);
			break;
		case TWAIN_STATE_CONFIG_CHANGE :
			rc = do_set_config(dev, new_config);
			if( rc != 0 ) {
				usb_ep_set_halt(dev->gadget->ep0);
			} 
			break;
		case TWAIN_STATE_DISCONNECT :
			break;
		case TWAIN_STATE_INTERFACE_CHANGE :
			rc = do_set_interface(dev, 0);	
			if( rc != 0 ) {
				usb_ep_set_halt(dev->gadget->ep0);
			} 
			break;
		default :
			break;
	}
	
}
static int twain_main_thread(void *dev_)
{
	struct twain_dev *dev = (struct twain_dev *)dev_;

	dev->thread_task = current;
	daemonize("twain-gadget");

	siginitsetinv(&dev->thread_signal_mask, sigmask(SIGINT) |
			sigmask(SIGTERM) | sigmask(SIGKILL) | sigmask(SIGUSR1));
	sigprocmask(SIG_SETMASK, &dev->thread_signal_mask, NULL);

	wait_for_completion(&dev->thread_notifier);

	while( dev->state != TWAIN_STATE_TERMINATED ) {
		printk(KERN_ALERT "====%d\n", dev->state);
		if( exception_in_progress(dev) || signal_pending(current) ) {
			handle_exception(dev);
			continue;
		}
		if( list_empty(&dev->preview_queue) && list_empty(&dev->bulk_queue)) {
			sleep_thread(dev);
		} else {
			if( !list_empty(&dev->preview_queue) ) {
				start_transfer(dev, QUEUE_ID_PREVIEW_FULL);
			} else {
				start_transfer(dev, QUEUE_ID_IMGBULK_FULL);
			}
			continue;
		}
		spin_lock(&dev->lock);
		if( !exception_in_progress(dev) ) {
			dev->state = TWAIN_STATE_IDLE;
		}
		spin_unlock(&dev->lock);
	}
	dev->thread_task = NULL;
	flush_signals(current);

	if( test_and_clear_bit(REGISTERED, &dev->atomic_bitflags) ) {
		usb_gadget_unregister_driver(&twain_driver);
	}

	complete_and_exit(&dev->thread_notifier, 0);
}

static void twain_gadget_unbind (struct usb_gadget *gadget)
{
	struct twain_dev		*dev = get_gadget_data (gadget);

	DBG (dev, "unbind\n");
	clear_bit(REGISTERED, &dev->atomic_bitflags);

	if( dev->state != TWAIN_STATE_TERMINATED ) {
		raise_exception(dev, TWAIN_STATE_EXIT);
		wait_for_completion(&dev->thread_notifier);
		complete(&dev->thread_notifier);
	}
	/* we've already been disconnected ... no i/o is active */
	if (dev->ctrlreq)
		free_ep_req (gadget->ep0, dev->ctrlreq);

	buffers_free(dev);
//	kfree (dev);
	set_gadget_data (gadget, NULL);

}

static int
twain_gadget_bind (struct usb_gadget *gadget)
{
	struct twain_dev		*dev = twdev;
	struct usb_ep		*ep;
	int			gcnum;
	int		rc;

	if( !dev ) {
		printk(KERN_ERR "%s: no initilize gadget device!\n",shortname);
		return -ENODEV;
	}
	usb_ep_autoconfig_reset(gadget);

	ep = usb_ep_autoconfig(gadget, &hs_preview_desc);
	if (!ep) {
autoconf_fail:
		printk (KERN_ERR "%s: can't autoconfigure on %s\n",
			shortname, gadget->name);
		return -ENODEV;
	}
	EP_PREVIEW = ep->name;
	ep->driver_data = ep;	/* claim in preview endpoint*/

	ep = usb_ep_autoconfig(gadget, &hs_outcmd_desc);
	if (!ep) {
		goto autoconf_fail;
	}
	EP_OUTCMD_NAME = ep->name;
	ep->driver_data = ep;	/* claim out cmd endpoint*/

	ep = usb_ep_autoconfig(gadget, &hs_incmd_desc);
	if (!ep) {
		goto autoconf_fail;
	}
	EP_INCMD_NAME = ep->name;
	ep->driver_data = ep;	/* claim in cmd endpoint*/

	ep = usb_ep_autoconfig(gadget, &hs_in_bulk_desc);
	if( !ep ) {
		goto autoconf_fail;
	}
	EP_INBULK_NAME = ep->name;
	ep->driver_data = ep;	/* claim in bulk endpoint */

	gcnum = usb_gadget_controller_number(gadget);
	if (gcnum >= 0)
		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
	else {
		printk (KERN_WARNING "%s: controller '%s' not recognized\n",
			shortname, gadget->name);
		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
	}

	/* ok, we made sense of the hardware ... */
	dev->gadget = gadget;
	set_gadget_data(gadget, dev);

	/* preallocate control response and buffer for end point 0*/
	dev->ctrlreq = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
	if (!dev->ctrlreq)
		goto enomem;
	dev->ctrlreq->buf = usb_ep_alloc_buffer(gadget->ep0, EP0_BUFSIZ,
				&dev->ctrlreq->dma, GFP_KERNEL);
	if (!dev->ctrlreq->buf)
		goto enomem;

	dev->ctrlreq->complete = twain_gadget_setup_complete;

	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

	/* assume ep0 uses the same value for both speeds ... */
	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;

	if (gadget->is_otg) {	/* not support in this twain driver */
		otg_descriptor.bmAttributes |= USB_OTG_HNP,
		twain_usb_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	usb_gadget_set_selfpowered(gadget);

	gadget->ep0->driver_data = dev;
	/* Allocate the data buffers */
	if( buffers_alloc(dev) ) {
		goto enomem;
	}

	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
	INFO (dev, "using %s, OUTCMD: [%s] INCMD: [%s] INBULK: [%s] PREVIEW: [%s]\n",gadget->name, EP_OUTCMD_NAME, EP_INCMD_NAME, EP_INBULK_NAME,EP_PREVIEW);

	snprintf (manufacturer, sizeof manufacturer, "%s %s with %s",
		system_utsname.sysname, system_utsname.release,
		gadget->name); /* Store machine information */

	if( (rc = kernel_thread(twain_main_thread, dev, (CLONE_VM | CLONE_FS 
						| CLONE_FILES))) < 0) {
		goto enomem;
	}
	dev->thread_pid = rc;

	return 0;
enomem:
	dev->state = TWAIN_STATE_TERMINATED;
	twain_gadget_unbind(dev->gadget);
	return -ENOMEM;
}



static void
twain_gadget_suspend (struct usb_gadget *gadget)
{
	struct twain_dev		*dev = get_gadget_data (gadget);
	set_bit(SUSPENDED, &dev->atomic_bitflags);

}

static void
twain_gadget_resume (struct usb_gadget *gadget)
{
	struct twain_dev		*dev = get_gadget_data (gadget);
	clear_bit(SUSPENDED, &dev->atomic_bitflags);
}



static struct usb_gadget_driver twain_driver = {
	.speed		= USB_SPEED_HIGH,
	.function	= (char *) longname,
	.bind		= twain_gadget_bind,
	.unbind		= twain_gadget_unbind,

	.setup		= twain_gadget_setup,
	.disconnect	= twain_gadget_disconnect,

	.suspend	= twain_gadget_suspend,
	.resume		= twain_gadget_resume,

	.driver 	= {
		.name		= (char *) shortname,
	},
};

MODULE_AUTHOR ("Insighten");
MODULE_LICENSE ("Dual BSD/GPL");

static int __init init (void)
{
	int rc;

	twdev = twain_dev_alloc();
	if( twdev == NULL) {
		return -ENOMEM;
	}
	if( twain_cdev_setup(twdev) < 0 ) {
		printk(KERN_ERR "Can't setup char device.\n");
		goto enomem;
	}
	rc = usb_gadget_register_driver (&twain_driver);
	if( rc != 0 ) {
		printk(KERN_ERR "Can't register_usb_driver.\n");
		goto fail;
	}
	complete(&twdev->thread_notifier);
	return 0;
fail:
	twain_cdev_cleanup(twdev);
enomem:
	twain_dev_free(twdev);
	return -ENOMEM;
}
module_init (init);

static void __exit cleanup (void)
{
	struct twain_dev *dev = twdev;

	usb_gadget_unregister_driver (&twain_driver);
	twain_cdev_cleanup(dev);
	twain_dev_free(dev);

}
module_exit (cleanup);


